using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;

namespace LHS.Win
{
    public class CryptoLib
    {
        // Fields
        private static CryptoLib _DES = null;
        private SymmetricAlgorithm mCryptoService = null;
        private ICryptoTransform mDecryptor = null;
        private ICryptoTransform mEncryptor = null;

        // Methods
        public CryptoLib(string sKey, Providers cryptoType)
        {
            switch (cryptoType)
            {
                case Providers.DES:
                    this.mCryptoService = new DESCryptoServiceProvider();
                    break;

                case Providers.RC2:
                    this.mCryptoService = new RC2CryptoServiceProvider();
                    break;

                case Providers.Rijndael:
                    this.mCryptoService = new RijndaelManaged();
                    break;

                case Providers.TripleDes:
                    this.mCryptoService = new TripleDESCryptoServiceProvider();
                    break;
            }
            byte[] legalKey = this.GetLegalKey(sKey);
            if ((cryptoType == Providers.Rijndael) && (legalKey.Length != 0x10))
            {
                sKey = sKey.Substring(0, 8);
                legalKey = this.GetLegalKey(sKey);
            }
            this.mCryptoService.Key = legalKey;
            this.mCryptoService.Mode = CipherMode.ECB;
            this.mEncryptor = this.mCryptoService.CreateEncryptor();
            this.mDecryptor = this.mCryptoService.CreateDecryptor();
        }

        public string Decrypt(string s)
        {
            string str = (s == null) ? string.Empty : s;
            if (str.Length > 0)
            {
                byte[] inputBuffer = Convert.FromBase64String(str);
                return Encoding.UTF8.GetString(this.mDecryptor.TransformFinalBlock(inputBuffer, 0, inputBuffer.Length));
            }
            return str;
        }

        public string DecryptWeb(object s)
        {
            string str = (s == null) ? string.Empty : s.ToString().Trim().Replace(" ", "+");
            return this.Decrypt(str);
        }

        public string Encrypt(string s)
        {
            string str = (s == null) ? string.Empty : s;
            if (str.Length > 0)
            {
                byte[] bytes = Encoding.UTF8.GetBytes(str);
                return Convert.ToBase64String(this.mEncryptor.TransformFinalBlock(bytes, 0, bytes.Length));
            }
            return str;
        }

        private byte[] GetLegalKey(string Key)
        {
            string s = Key;
            if (this.mCryptoService.LegalKeySizes.Length > 0)
            {
                int minSize = this.mCryptoService.LegalKeySizes[0].MinSize;
                if ((s.Length * 8) > this.mCryptoService.LegalKeySizes[0].MaxSize)
                {
                    s = s.Substring(0, this.mCryptoService.LegalKeySizes[0].MaxSize / 8);
                }
                else if ((s.Length * 8) < minSize)
                {
                    if (this.mCryptoService.LegalKeySizes[0].SkipSize == 0)
                    {
                        s = s.PadRight(minSize / 8, ' ');
                    }
                    else
                    {
                        while ((s.Length * 8) > minSize)
                        {
                            minSize += this.mCryptoService.LegalKeySizes[0].SkipSize;
                        }
                        s = s.PadRight(minSize / 8, ' ');
                    }
                }
            }
            return Encoding.ASCII.GetBytes(s);
        }

        // Properties
        public static CryptoLib DES
        {
            get
            {
                if (_DES == null)
                {
                    _DES = new CryptoLib("CryptoLib", Providers.DES);
                }
                return _DES;
            }
        }

        // Nested Types
        public enum Providers
        {
            DES,
            RC2,
            Rijndael,
            TripleDes
        }
    }
}
